#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_thread.h>
#include <SDL2/SDL_ttf.h>
#include <SDL2/SDL_opengl.h>
#include <GL/glu.h>
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <fstream>
#include "global.h"
#include "ltimer.h"

/* 
sdl2 OpenGL 演示
*/

//全部面积大小
// 由于渲染的大小不再是屏幕的大小，必须有一组单独的常量来定义渲染的大小。
const int LEVEL_WIDTH = 1280;
const int LEVEL_HEIGHT = 960;

//当前框大小
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;

TTF_Font* gFont = nullptr; 
// 渲染的窗口
SDL_Window * gWindow = nullptr;

//Render text r,g,b,a
SDL_Color textColor = { 0, 0xff, 0xff, 0xff };

//OpenGL context  OpenGL 上下文就是处理 OpenGL 调用的东西，任何 OpenGL 渲染都需要它
SDL_GLContext gContext;

//Render flag  用于切换渲染的标志
bool gRenderQuad = true;

bool initGL()
{
    bool success = true;
    GLenum error = GL_NO_ERROR;

    //Initialize Projection Matrix  初始化投影矩阵，它控制着 OpenGL 中透视的工作方式
    glMatrixMode( GL_PROJECTION );
    // 将其初始化为身份矩阵
    glLoadIdentity();
    
    //Check for error
    error = glGetError();
    if( error != GL_NO_ERROR )
    {
        printf( "Error initializing OpenGL! %s\n", gluErrorString( error ) );
        success = false;
    }

    //Initialize Modelview Matrix  模型视图矩阵做同样的处理，该矩阵控制如何查看和放置渲染对象
    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();

    //Check for error
    error = glGetError();
    if( error != GL_NO_ERROR )
    {
        printf( "Error initializing OpenGL! %s\n", gluErrorString( error ) );
        success = false;
    }

    //Initialize clear color  设置透明色，即调用 glClear 时擦拭屏幕的颜色
    glClearColor( 0.f, 0.f, 0.f, 1.f );
    
    //Check for error
    error = glGetError();
    if( error != GL_NO_ERROR )
    {
        printf( "Error initializing OpenGL! %s\n", gluErrorString( error ) );
        success = false;
    }
    
    return success;
}

// 按键输入处理程序会切换渲染标志
void handleKeys( unsigned char key, int x, int y )
{
    //Toggle quad
    if( key == 'q' )
    {
        gRenderQuad = !gRenderQuad;
    }
}

// 更新处理程序只是为了兼容性而设置的
void update()
{
    //No per frame update needed
}

// 在渲染器中，我们会清空屏幕，然后如果启用了渲染，我们就会渲染一个四边形
void render()
{
    //Clear color buffer
    glClear( GL_COLOR_BUFFER_BIT );
    
    //Render quad
    if( gRenderQuad )
    {
        glBegin( GL_QUADS );
        // OpenGL 使用归一化坐标,坐标原点在屏幕中心，和sdl2不同  为了获得类似 SDL 的坐标系，必须将项目矩阵设置为正交透视
            glVertex2f( -0.5f, -0.5f );
            glVertex2f( 0.5f, -0.5f );
            glVertex2f( 0.5f, 0.5f );
            glVertex2f( -0.5f, 0.5f );
        glEnd();
    }
}

bool init()
{
     //Initialization flag
    bool success = true;

    //Initialize SDL
    if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
    {
        std::cout << "SDL could not initialize! SDL_Error: " << SDL_GetError() << std::endl;
        success = false;
    }
    else
    {
        //Use OpenGL 2.1
        /*
        在创建窗口之前，需要指定所需的版本。需要的是 OpenGL 2.1，因此需要调用 SDL_GL_SetAttribute 将主要版本设置为 2，次要版本设置为 1。
        设置好版本后，可以通过向 SDL_CreateWindow 传递 SDL_WINDOW_OPENGL 标志来创建 OpenGL 窗口了
        */
        SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 2 );
        SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 1 );

        //Create window
        gWindow = SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_OPENGL |SDL_WINDOW_SHOWN );
        if( gWindow == nullptr )
        {
            std:: cout << "Window could not be created! SDL_Error: " << SDL_GetError() << std::endl;
            success = false;
        }
        else
        {
            ///Create context   SDL_GL_CreateContext 创建 OpenGL 渲染上下文
            gContext = SDL_GL_CreateContext( gWindow );
            if( gContext == nullptr )
            {
                std::cout << "OpenGL context could not be created! SDL Error:" << SDL_GetError() << std::endl;
                success = false;
            }
            else
            {
                //Use Vsync  使用 SDL_GL_SetSwapInterval 启用 Vsync
                if( SDL_GL_SetSwapInterval( 1 ) < 0 )
                {
                    std::cout << "Warning: Unable to set VSync! SDL Error: " << SDL_GetError() << std::endl;
                }
                //Initialize OpenGL   用initGL 函数初始化 OpenGL 的内部结构
                if( !initGL() )
                {
                    std::cout << "Unable to initialize OpenGL!" << std::endl;
                    success = false;
                }                
            }

        }
    }

    return success;
}

bool loadMedia()
{
    //Loading success flag
    bool success = true;

    //Load data stream
    // if( !gSplashTexture.loadFromFile("splash.png")  )
    // {        
    //     std::cout << "Failed to load splash texture!" << std::endl;
    //     success = false;
    // }
    // 像素加载完成后，对像素进行处理，使所有背景像素透明
    // else
    // {
    //     //Get pixel data
    //     //获取一个指向像素的指针，并获得要遍历的像素数
    //     Uint32* pixels = gFooTexture.getPixels32();
    //     int pixelCount = gFooTexture.getPitch32() * gFooTexture.getHeight();

    //     //Map colors
    //     //映射色键（本例中使用品红色）和透明色
    //     Uint32 colorKey = SDL_MapRGBA( SDL_GetWindowSurface( gWindow )->format, 0xFF, 0x00, 0xFF, 0xFF );
    //     Uint32 transparent = SDL_MapRGBA( SDL_GetWindowSurface( gWindow )->format, 0xFF, 0xFF, 0xFF, 0x00 );

    //     //Color key pixels
    //     for( int i = 0; i < pixelCount; ++i )
    //     {
    //         if( pixels[ i ] == colorKey )
    //         {
    //             // 找到所有关键色的像素，然后用透明像素替换它们
    //             pixels[ i ] = transparent;
    //         }
    //     }

    //     //Create texture from manually color keyed pixels
    //     if( !gFooTexture.loadFromPixels() )
    //     {
    //         std::cout << "Unable to load Foo' texture from surface!" << std::endl;
    //     }
    // }

    return success;
}

void close()
{
    //Destroy windows
    SDL_DestroyWindow(gWindow);
    gWindow = nullptr;
    // SDL_DestroyRenderer(gRenderer);
    // gRenderer = nullptr;

    //Destroy the mutex
    SDL_DestroyMutex( gBufferLock );
    gBufferLock = nullptr;
            
    //Destroy conditions
    SDL_DestroyCond( gCanProduce );
    SDL_DestroyCond( gCanConsume );
    gCanProduce = nullptr;
    gCanConsume = nullptr;

    //Quit SDL subsystems
    // TTF_Quit();
    // Mix_Quit();
    IMG_Quit();
    SDL_Quit();
}

int main( int argc, char* args[] )
{
    //Start up SDL and create window
    if( !init() )
    {
        std::cout << "Failed to initialize!" << std::endl;
    }
    else
    {
        //Hack to get window to stay up
        SDL_Event e; 
        bool quit = false; 

        //Enable text input
        SDL_StartTextInput();

        //While application is running
        while( !quit )
        {
            //Handle events on queue
            while( SDL_PollEvent( &e ) != 0 )
            {
                //User requests quit
                if( e.type == SDL_QUIT )
                {
                    quit = true;
                }
                //Handle keypress with current mouse position
                else if( e.type == SDL_TEXTINPUT )
                {
                    int x = 0, y = 0;
                    SDL_GetMouseState( &x, &y );
                    handleKeys( e.text.text[ 0 ], x, y );
                }
            }
            //Render quad
            render();
            
            //Update screen
            SDL_GL_SwapWindow( gWindow );
        }
        //Disable text input
        SDL_StopTextInput();
    }
    close();

    return 0;
}



